﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace ERModelData
{
    /// <summary>Класс для трансформации сущности</summary>
    class Transformation : Markers
    {
        /// <summary>[Key] Объект игнорирует собственный вызов</summary>
        public bool IgnoreCall { get; set; }

        /// <summary>Конструктор класса</summary>
        public Transformation(Property property)
        {
            HidenMarkers();

            this.property = property;

            TopLeft = CreateMarker();
            TopLeft.Name = "TopLeft";
            TopLeft.Cursor = Cursors.SizeNWSE;
            TopLeft.MouseLeftButtonDown += new MouseButtonEventHandler(BeginScale);

            Top = CreateMarker();
            Top.Name = "Top";
            Top.Cursor = Cursors.SizeNS;
            Top.MouseLeftButtonDown += new MouseButtonEventHandler(BeginScale);

            TopRight = CreateMarker();
            TopRight.Name = "TopRight";
            TopRight.Cursor = Cursors.SizeNESW;
            TopRight.MouseLeftButtonDown += new MouseButtonEventHandler(BeginScale);

            Right = CreateMarker();
            Right.Name = "Right";
            Right.Cursor = Cursors.SizeWE;
            Right.MouseLeftButtonDown += new MouseButtonEventHandler(BeginScale);

            BottomRight = CreateMarker();
            BottomRight.Name = "BottomRight";
            BottomRight.Cursor = Cursors.SizeNWSE;
            BottomRight.MouseLeftButtonDown += new MouseButtonEventHandler(BeginScale);

            Bottom = CreateMarker();
            Bottom.Name = "Bottom";
            Bottom.Cursor = Cursors.SizeNS;
            Bottom.MouseLeftButtonDown += new MouseButtonEventHandler(BeginScale);

            BottomLeft = CreateMarker();
            BottomLeft.Name = "BottomLeft";
            BottomLeft.Cursor = Cursors.SizeNESW;
            BottomLeft.MouseLeftButtonDown += new MouseButtonEventHandler(BeginScale);

            Left = CreateMarker();
            Left.Name = "Left";
            Left.Cursor = Cursors.SizeWE;
            Left.MouseLeftButtonDown += new MouseButtonEventHandler(BeginScale);
        }

        /// <summary>Отображение маркеров трансформации сущности</summary>
        /// <param name="essence">Выделеная сущность</param>
        public void Show(Essence essence)
        {
            if (IgnoreCall) return;

            this.essence = essence;
            this.canvas = (Canvas)essence.Parent;

            property.SelectEssence(essence);

            ShowMarkers();
            this.essence.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(BeginMove);
            IgnoreCall = false;
        }

        /// <summary>Сокрытие маркеров трансформации сущности</summary>
        public void Hiden() { HidenMarkers(); if(!IgnoreCall) property.ClearProperty(); }

        ///////////////////////////////////////////////////////////////////////////////////
        //////                       Внутриние методы и свойства                    ///////
        ///////////////////////////////////////////////////////////////////////////////////

        private Property property;

        /// <summary>[static] Создание маркера</summary>
        /// <returns>Созданный маркер</returns>
        private static Ellipse CreateMarker()
        {
            Ellipse Marker = new Ellipse();
            Marker.Width = 6;
            Marker.Height = 6;
            Marker.StrokeThickness = 3;
            Marker.Stroke = Brushes.Black;
            return Marker;
        }

        ///////////////////////////////////////////////////////////////////////////////////
        //////                       Изменение размеров сущности                    ///////
        ///////////////////////////////////////////////////////////////////////////////////

        /// <summary>Маркер, с помощью которого ведется изменение размера сущности</summary>
        Ellipse selectMarker;

        /// <summary>[Event Handler] Начало операции: изменение размеров сущности</summary>
        private void BeginScale(object sender, MouseButtonEventArgs e)
        {
            selectMarker = (Ellipse)sender;
            canvas.MouseMove += new MouseEventHandler(Scale);
            canvas.MouseLeftButtonUp += new MouseButtonEventHandler(EndScale);
        }

        /// <summary>[Event Handler] Выполнение операции: изменение размеров сущности</summary>
        private void Scale(object sender, MouseEventArgs e)
        {
            switch (selectMarker.Name)
            {
                case "TopLeft":
                    essence.Width -= e.GetPosition(canvas).X - Canvas.GetLeft(essence);
                    Canvas.SetLeft(essence, e.GetPosition(canvas).X);
                    essence.Height -= e.GetPosition(canvas).Y - Canvas.GetTop(essence);
                    Canvas.SetTop(essence, e.GetPosition(canvas).Y);
                    UpdatePositionMarkers();
                    break;
                case "Top":
                    essence.Height -= e.GetPosition(canvas).Y - Canvas.GetTop(essence);
                    Canvas.SetTop(essence, e.GetPosition(canvas).Y);
                    UpdatePositionMarkers();
                    break;
                case "TopRight":
                    essence.Width += e.GetPosition(canvas).X - (Canvas.GetLeft(essence) + essence.Width);
                    UpdatePositionMarkers();
                    essence.Height -= e.GetPosition(canvas).Y - Canvas.GetTop(essence);
                    Canvas.SetTop(essence, e.GetPosition(canvas).Y);
                    UpdatePositionMarkers();
                    break;
                case "Right":
                    essence.Width += e.GetPosition(canvas).X - (Canvas.GetLeft(essence) + essence.Width);
                    UpdatePositionMarkers();
                    break;
                case "BottomRight":
                    essence.Width += e.GetPosition(canvas).X - (Canvas.GetLeft(essence) + essence.Width);
                    essence.Height += e.GetPosition(canvas).Y - (Canvas.GetTop(essence) + essence.Height);
                    UpdatePositionMarkers();
                    break;
                case "Bottom":
                    essence.Height += e.GetPosition(canvas).Y - (Canvas.GetTop(essence) + essence.Height);
                    UpdatePositionMarkers();
                    break;
                case "BottomLeft":
                    essence.Width -= e.GetPosition(canvas).X - Canvas.GetLeft(essence);
                    Canvas.SetLeft(essence, e.GetPosition(canvas).X);
                    essence.Height += e.GetPosition(canvas).Y - (Canvas.GetTop(essence) + essence.Height);
                    UpdatePositionMarkers();
                    break;
                case "Left":
                    essence.Width -= e.GetPosition(canvas).X - Canvas.GetLeft(essence);
                    Canvas.SetLeft(essence, e.GetPosition(canvas).X);
                    UpdatePositionMarkers();
                    break;
            }
        }

        /// <summary>[Event Handler] Окончание операции операции: изменение размеров сущности</summary>
        public void EndScale(object sender, MouseButtonEventArgs e)
        {
            canvas.MouseMove -= Scale;
            canvas.MouseLeftButtonUp -= EndScale;
        }

        ///////////////////////////////////////////////////////////////////////////////////
        //////                           Перемещение сущности                       ///////
        ///////////////////////////////////////////////////////////////////////////////////

        /// <summary>Смещение позиции курсора относительно верхнего левого угла сущности</summary>
        Size dLocotion;

        /// <summary>[Event Handler] Начало операции: перемещение сущности</summary>
        private void BeginMove(object sender, MouseButtonEventArgs e)
        {
            essence.Cursor = Cursors.SizeAll;
            dLocotion.Width = e.GetPosition(canvas).X - Canvas.GetLeft(essence);
            dLocotion.Height = e.GetPosition(canvas).Y - Canvas.GetTop(essence);
            canvas.MouseMove += new MouseEventHandler(Move);
            canvas.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(EndMove);
        }

        /// <summary>[Event Handler] Выполнение операции: перемещение сущности</summary>
        private void Move(object sender, MouseEventArgs e)
        {
            Canvas.SetLeft(essence, e.GetPosition(canvas).X - dLocotion.Width);
            Canvas.SetTop(essence, e.GetPosition(canvas).Y - dLocotion.Height);
            UpdatePositionMarkers();
        }

        /// <summary>[Event Handler] Окончание операции операции: перемещение сущности</summary>
        public void EndMove(object sender, MouseButtonEventArgs e)
        {
            essence.Cursor = Cursors.Arrow;
            canvas.MouseMove -= Move;
            canvas.MouseLeftButtonUp -= EndMove;
        }
    }
}
